home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 2 / Amiga Tools 2.iso / tex / macros / source / contrib / fp / fp-basic.sty < prev    next >
Text File  |  1995-03-09  |  28KB  |  1,049 lines

  1. \NeedsTeXFormat{LaTeX2e}
  2. \ProvidesPackage{fp-basic}[1995/02/17]
  3.  
  4. %version information
  5. \def\FP@basicversion{1.2}
  6. \message{%
  7.   `Basic Fixed Point Arithmetic',\space%
  8.   Version \FP@basicversion%
  9.   \space(C) Michael Mehlich%
  10. }
  11.  
  12. %fixed point arithmetic with values between (including)
  13. %      -999999999999999999.999999999999999999
  14. % and  +999999999999999999.999999999999999999
  15.  
  16. %%%public area (macros which may be used)%%%
  17.  
  18. %binary operations
  19. \def\FPadd#1#2#3{\FP@callc\FP@add#1{#2}{#3}+\relax} % #1 := #2+#3
  20. \def\FPdiv#1#2#3{\FP@callc\FP@div#1{#2}{#3}}        % #1 := #2/#3
  21. \def\FPmul#1#2#3{\FP@callc\FP@mul#1{#2}{#3}}        % #1 := #2*#3
  22. \def\FPsub#1#2#3{\FP@callc\FP@add#1{#2}{-#3}-\relax}% #1 := #2-#3
  23. %unary operations
  24. \def\FPabs#1#2{\FP@calld\FP@abs#1{#2}}              % #1 := abs(#2)
  25. \def\FPneg#1#2{\FP@calld\FP@neg#1{#2}}              % #1 := -#2
  26. %binary relations
  27. \def\FPiflt#1#2{\FP@callb\FP@iflt{#1}{#2}+\relax}   % #1 < #2 ?
  28. \def\FPifeq#1#2{\FP@callb\FP@ifeq{#1}{#2}}          % #1 = #2 ?
  29. \def\FPifgt#1#2{\FP@callb\FP@iflt{#2}{#1}-\relax}   % #1 > #2 ?
  30. %unary relations
  31. \def\FPifneg#1{\FP@calla\FP@ifneg{#1}}              % #1 <  0 ?
  32. \def\FPifpos#1{\FP@calla\FP@ifpos{#1}}              % #1 >= 0 ?
  33. \def\FPifzero#1{\FP@calla\FP@ifzero{#1}}            % #1 =  0 ?
  34. \def\FPifint#1{\FP@calla\FP@ifint{#1}}              % #1 is integer ?
  35. %repeat last test
  36. %\ifFPtest                                          % repeat last test
  37.  
  38. %%%private fp-area (don't use these macros)%%%
  39.  
  40. % To debug FP functions (enable intermediate messages on computations)
  41. \newif\ifFPdebug
  42. \FPdebugfalse
  43. \def\FP@debug#1{\ifFPdebug\typeout{FP debug: #1}\fi}
  44.  
  45. %conditional printing of messages (only if \FPmessagestrue defined)
  46. \newif\ifFPmessages
  47. \FPmessagestrue
  48. \def\FP@beginmessage#1{\ifFPmessages\message{( FP-#1}\fi}
  49. \def\FP@endmessage#1{\ifFPmessages\message{)}\fi}
  50. \def\FP@errmessage#1{\errmessage{FP error: #1!}}
  51. \def\FP@warnmessage#1{\message{FP warning: #1!}}
  52.  
  53. %allocation of registers
  54.  
  55. \newcount\FP@xs %sign of 1st value
  56. \newcount\FP@xia%integer part of 1st value
  57. \newcount\FP@xib%integer part of 1st value
  58. \newcount\FP@xfa%fractional part of 1st value
  59. \newcount\FP@xfb%fractional part of 1st value
  60.  
  61. \countdef\FP@ys=5 %sign of 2nd value
  62. \countdef\FP@yia=6%integer part of 2nd value
  63. \countdef\FP@yib=7%integer part of 2nd value
  64. \countdef\FP@yfa=8%fractional part of 2nd value
  65. \countdef\FP@yfb=9%fractional part of 2nd value
  66.  
  67. \countdef\FP@xk=10  %registers for splitting 1st value
  68. \countdef\FP@xl=11
  69. \countdef\FP@xm=12
  70. \countdef\FP@xn=13
  71. \countdef\FP@xo=14
  72. \countdef\FP@xp=15
  73. \countdef\FP@xq=16
  74. \countdef\FP@xr=17
  75. \countdef\FP@xz=18
  76. \countdef\FP@xt=19
  77. \countdef\FP@xu=20
  78. \countdef\FP@xv=21
  79.  
  80. \countdef\FP@yk=22 %registers for splitting 2nd value
  81. \countdef\FP@yl=23
  82. \countdef\FP@ym=24
  83. \countdef\FP@yn=25
  84. \countdef\FP@yo=26
  85. \countdef\FP@yp=27
  86. \countdef\FP@yq=28
  87. \countdef\FP@yr=29
  88. \countdef\FP@yz=30
  89. \countdef\FP@yt=31
  90. \countdef\FP@yu=32
  91. \countdef\FP@yv=33
  92.  
  93. \newcount\FP@rega   %auxiliary registers
  94. \newcount\FP@regb
  95. \countdef\FP@regc=36
  96. \countdef\FP@regd=37
  97. \countdef\FP@rege=38
  98.  
  99. \countdef\FP@rs=39 %result registers
  100. \countdef\FP@ria=40
  101. \countdef\FP@rib=41
  102. \countdef\FP@rfa=42
  103. \countdef\FP@rfb=43
  104.  
  105. \newcount\FP@regs    %local auxiliary registers
  106. \countdef\FP@count=45
  107. \countdef\FP@res=46
  108. \countdef\FP@shift=47
  109. \newcount\FP@times
  110. \countdef\FP@prod=49
  111.  
  112. %auxiliary macros which may be used in all of the following macros
  113. \newif\ifFP@test
  114.  
  115. \def\FP@ignorenext#1{}
  116. \def\FP@first#1#2\relax{#1}
  117. \def\FP@swallow#1\relax{}
  118.  
  119. \def\ifFP@zero#1{%
  120.   \ifnum%
  121.     \expandafter\ifnum\csname FP@#1ia\endcsname=0 0\else1\fi%
  122.     \expandafter\ifnum\csname FP@#1ib\endcsname=0 0\else1\fi%
  123.     \expandafter\ifnum\csname FP@#1fa\endcsname=0 0\else1\fi%
  124.     \expandafter\ifnum\csname FP@#1fb\endcsname=0 0\else1\fi%
  125.     =0\relax%
  126. }
  127.  
  128. %read value
  129.  
  130. \def\FP@correctintcounter#1\relax{%
  131.   {\edef\FP@tmp{#1}%
  132.    \FP@count=0\relax%
  133.    \loop%
  134.      \edef\FP@tmpa{\expandafter\FP@first\FP@tmp\noexpand\relax}%
  135.      \expandafter\ifx\FP@tmpa0\relax%
  136.         \advance\FP@count1\relax%
  137.         \edef\FP@tmp{\expandafter\FP@ignorenext\FP@tmp}%
  138.      \repeat%
  139.    \ifnum\FP@count>18\relax%
  140.      \FP@errmessage{Overflow}%
  141.    \fi%
  142.    \expandafter\if!\FP@tmp!%
  143.      \advance\FP@count-18\relax%
  144.      \FP@count=-\FP@count%
  145.      \loop%
  146.        \ifnum\FP@count>0\relax%
  147.           \FP@regc=\FP@rega%
  148.       \divide\FP@rega10\relax\multiply\FP@rega10\relax%
  149.       \advance\FP@regc-\FP@rega\multiply\FP@regc100000000\relax%
  150.       \divide\FP@rega10\relax%
  151.       \divide\FP@regb10\relax\advance\FP@regb\FP@regc%
  152.       \advance\FP@count-1\relax%
  153.        \repeat%
  154.      \global\FP@rega=\FP@rega%
  155.      \global\FP@regb=\FP@regb%
  156.    \else%
  157.      \FP@errmessage{Number too big}%
  158.    \fi%
  159.   }%
  160. }
  161. \def\FP@@setintcounter#1#2#3#4#5#6#7#8#9{%
  162.   \FP@regb=#1#2#3#4#5#6#7#8#9\relax%
  163.   \FP@correctintcounter%
  164. }
  165. \def\FP@setintcounter#1#2#3#4#5#6#7#8#9{%
  166.   \FP@rega=#1#2#3#4#5#6#7#8#9\relax%
  167.   \FP@@setintcounter%
  168. }
  169.  
  170. \def\FP@@setfractcounter#1#2#3#4#5#6#7#8#9{%
  171.   \FP@regb=#1#2#3#4#5#6#7#8#9\relax%
  172.   \FP@swallow%
  173. }
  174. \def\FP@setfractcounter#1#2#3#4#5#6#7#8#9{%
  175.   \FP@rega=#1#2#3#4#5#6#7#8#9\relax%
  176.   \FP@@setfractcounter%
  177. }
  178.  
  179. \def\FP@getsign#1\relax{%
  180.   {\FP@regs=1\relax%
  181.    \edef\FP@tmp{#1}%
  182.    \loop%
  183.      \edef\FP@tmpa{\expandafter\FP@first\FP@tmp\noexpand\relax}%
  184.      \expandafter\ifx\FP@tmpa-\relax%
  185.         \multiply\FP@regs-1\relax%
  186.      \fi%
  187.      \ifnum\expandafter\ifx\FP@tmpa-1\else0\fi\expandafter\ifx\FP@tmpa+1\else0\fi>0%
  188.         \edef\FP@tmp{\expandafter\FP@ignorenext\FP@tmp}%
  189.      \repeat%
  190.    \global\let\FP@tmp\FP@tmp%
  191.    \global\FP@regs=\FP@regs%
  192.   }%
  193. }
  194.  
  195. \def\FP@removeleadingzeros#1\relax{%
  196.   {\edef\FP@tmp{#1}%
  197.    \loop%
  198.      \edef\FP@tmpa{\expandafter\FP@first\FP@tmp\noexpand\relax}%
  199.      \expandafter\ifx\FP@tmpa0\relax%
  200.        \edef\FP@tmp{\expandafter\FP@ignorenext\FP@tmp}%
  201.      \repeat%
  202.    \global\let\FP@tmp\FP@tmp%
  203.   }%
  204. }
  205.  
  206. \newif\ifFP@nonstop
  207. \def\FP@strip#1{%
  208.   {\edef\FP@tmp{#1}%
  209.    \edef\FP@tmpb{}%
  210.    \ifx\FP@tmp\@empty\else%
  211.      \FP@nonstoptrue%
  212.      \loop%
  213.        \edef\FP@tmpa{\expandafter\FP@first\FP@tmp\noexpand\relax}%
  214.        \expandafter\ifx\FP@tmpa-\relax\edef\FP@tmpb{\FP@tmpb\FP@tmpa}\else%
  215.        \expandafter\ifx\FP@tmpa+\relax\edef\FP@tmpb{\FP@tmpb\FP@tmpa}\else%
  216.        \expandafter\ifx\FP@tmpa0\relax\edef\FP@tmpb{\FP@tmpb\FP@tmpa}\else%
  217.        \expandafter\ifx\FP@tmpa1\relax\edef\FP@tmpb{\FP@tmpb\FP@tmpa}\else%
  218.        \expandafter\ifx\FP@tmpa2\relax\edef\FP@tmpb{\FP@tmpb\FP@tmpa}\else%
  219.        \expandafter\ifx\FP@tmpa3\relax\edef\FP@tmpb{\FP@tmpb\FP@tmpa}\else%
  220.        \expandafter\ifx\FP@tmpa4\relax\edef\FP@tmpb{\FP@tmpb\FP@tmpa}\else%
  221.        \expandafter\ifx\FP@tmpa5\relax\edef\FP@tmpb{\FP@tmpb\FP@tmpa}\else%
  222.        \expandafter\ifx\FP@tmpa6\relax\edef\FP@tmpb{\FP@tmpb\FP@tmpa}\else%
  223.        \expandafter\ifx\FP@tmpa7\relax\edef\FP@tmpb{\FP@tmpb\FP@tmpa}\else%
  224.        \expandafter\ifx\FP@tmpa8\relax\edef\FP@tmpb{\FP@tmpb\FP@tmpa}\else%
  225.        \expandafter\ifx\FP@tmpa9\relax\edef\FP@tmpb{\FP@tmpb\FP@tmpa}\else%
  226.        \ifx\FP@tmpa\@empty\FP@nonstopfalse\else%
  227.        \ifx\FP@tmpa\space\FP@nonstopfalse\else%
  228.          \FP@errmessage{Illegal character \FP@tmpa\space found in float number}
  229.        \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi%
  230.        \edef\FP@tmp{\expandafter\FP@ignorenext\FP@tmp}%
  231.        \ifx\FP@tmp\@empty\FP@nonstopfalse\fi%
  232.        \ifFP@nonstop%
  233.        \repeat%
  234.    \fi%
  235.    \global\let\FP@tmp\FP@tmpb%
  236.   }%
  237. }
  238.  
  239. \def\FP@readvalue#1#2#3{%
  240.   % #1    macro family to catch the value
  241.   % #2.#3 value
  242.   %
  243.   % regular expression [+|-]*[d]_0^18.[d]*
  244.   %
  245.   \FP@strip{#2}%
  246.   %sign
  247.   \expandafter\FP@getsign\FP@tmp\relax%
  248.   \csname FP@#1s\endcsname=\FP@regs%
  249.   %
  250.   %integer part
  251.   \FP@removeleadingzeros\FP@tmp\relax%
  252.   \expandafter\FP@setintcounter\FP@tmp000000000000000000\relax%
  253.   \csname FP@#1ia\endcsname=\FP@rega%
  254.   \csname FP@#1ib\endcsname=\FP@regb%
  255.   %
  256.   %fractional part
  257.   \FP@strip{#3}%
  258.   \expandafter\FP@setfractcounter\FP@tmp000000000000000000\relax%
  259.   \csname FP@#1fa\endcsname=\FP@rega%
  260.   \csname FP@#1fb\endcsname=\FP@regb%
  261.   %
  262.   %correct sign
  263.   \ifnum\FP@rega=0\relax%
  264.     \ifnum\FP@regb=0\relax%
  265.       \expandafter\ifnum\csname FP@#1ib\endcsname=0\relax%
  266.         \expandafter\ifnum\csname FP@#1ia\endcsname=0\relax%
  267.       \csname FP@#1s\endcsname=1\relax%
  268.     \fi%
  269.       \fi%
  270.     \fi%
  271.   \fi%
  272. }
  273.  
  274. %store value in macro
  275.  
  276. \def\FP@store#1#2{%
  277.   % #1 macro
  278.   % #2 macro family (value) to store
  279.   %
  280.   \ifFP@zero{#2}%
  281.     \csname FP@#2s\endcsname=1\relax%
  282.   \fi%
  283.   \expandafter\ifnum\csname FP@#2s\endcsname<0\relax%
  284.     \edef#1{-}%
  285.   \else%
  286.     \edef#1{}%
  287.   \fi%
  288.   \expandafter\ifnum\csname FP@#2ia\endcsname=0\relax%
  289.      \expandafter\ifnum\csname FP@#2ib\endcsname=0\relax%
  290.        \edef#1{#10}%
  291.      \else%
  292.        \edef#1{#1\expandafter\the\csname FP@#2ib\endcsname}%
  293.      \fi%
  294.   \else%
  295.     \expandafter\advance\csname FP@#2ib\endcsname1000000000\relax%
  296.     \edef#1{#1\expandafter\the\csname FP@#2ia\endcsname\expandafter\FP@ignorenext\the\csname FP@#2ib\endcsname}%
  297.   \fi%
  298.   \expandafter\advance\csname FP@#2fa\endcsname1000000000\relax%
  299.   \expandafter\advance\csname FP@#2fb\endcsname1000000000\relax%
  300.   \edef#1{#1\noexpand.\expandafter\FP@ignorenext\the\csname FP@#2fa\endcsname\expandafter\FP@ignorenext\the\csname FP@#2fb\endcsname}%
  301. }
  302.  
  303. %macros to expand some arguments
  304.  
  305. \def\FP@calla#1#2{%
  306.   % #1 macro to call
  307.   % #2 value
  308.   % expand the value and split them into the integer and the fractional part
  309.   \edef\next{\noexpand#1#2..\noexpand\relax}%
  310.   \next%
  311. }
  312.  
  313. \def\FP@callb#1#2#3{%
  314.   % #1 macro to call
  315.   % #2 1st value
  316.   % #3 2nd value
  317.   % expand the values and split them into the integer and the fractional parts 
  318.   \edef\next{\noexpand#1#2..\noexpand\relax#3..\noexpand\relax}%
  319.   \next%
  320. }
  321.  
  322. \def\FP@callc#1#2#3#4{%
  323.   % #1 macro to call
  324.   % #2 macro, which gets the result
  325.   % #3 1st value
  326.   % #4 2nd value
  327.   % expand the values and split them into the integer and the fractional parts
  328.   \edef\next{\noexpand#1\noexpand#2#3..\noexpand\relax#4..\noexpand\relax}%
  329.   \next%
  330. }
  331.  
  332. \def\FP@calld#1#2#3{%
  333.   % #1 macro to call
  334.   % #2 macro, which gets the result
  335.   % #3 value
  336.   \edef\next{\noexpand#1\noexpand#2#3..\noexpand\relax}%
  337.   \next%
  338. }
  339.  
  340. \def\FP@calle#1#2#3#4{%
  341.   % #1 macro to call
  342.   % #2 macro, which gets the first result
  343.   % #3 macro, which gets the second result
  344.   % #4 value
  345.   \edef\next{\noexpand#1\noexpand#2\noexpand#3#4..\noexpand\relax}%
  346.   \next%
  347. }
  348.  
  349. %add two values
  350.  
  351. \def\FP@add#1#2.#3.#4\relax#5.#6.#7\relax#8\relax{%
  352.   % #1 macro, which gets the result
  353.   % #2 integer part of 1st value 
  354.   % #3 fractional part of 1st value
  355.   % #4 dummy to swallow everthing after the 2nd '.'
  356.   % #5 integer part of 2nd value 
  357.   % #6 fractional part of 2nd value
  358.   % #7 dummy to swallow everthing after the 2nd '.'
  359.   %
  360.   {\ifx#8+\relax%
  361.      \FP@beginmessage{ADD}%
  362.    \else%
  363.      \FP@beginmessage{SUB}%
  364.    \fi%
  365.    %
  366.    \FP@readvalue{x}{#2}{#3}%
  367.    \FP@readvalue{y}{#5}{#6}%
  368.    %
  369.    \ifnum\FP@xs=\FP@ys%
  370.      \advance\FP@xfb\FP@yfb%
  371.      \advance\FP@xfa\FP@yfa%
  372.      \ifnum\FP@xfb<1000000000\relax\else%
  373.        \advance\FP@xfb-1000000000\relax%
  374.        \advance\FP@xfa1\relax%
  375.      \fi%
  376.      \advance\FP@xib\FP@yib%
  377.      \ifnum\FP@xfa<1000000000\relax\else%
  378.        \advance\FP@xfa-1000000000\relax%
  379.        \advance\FP@xib1\relax%
  380.      \fi%
  381.      \advance\FP@xia\FP@yia%
  382.      \ifnum\FP@xib<1000000000\relax\else%
  383.        \advance\FP@xib-1000000000\relax%
  384.        \advance\FP@xia1\relax%
  385.      \fi%
  386.      \ifnum\FP@xia<1000000000\relax\else%
  387.        \FP@errmessage{Overflow}%
  388.      \fi%
  389.      \FP@store\FP@tmp{x}%
  390.    \else%
  391.      \advance\FP@xfb-\FP@yfb%
  392.      \ifnum\FP@xfb<0\relax%
  393.        \advance\FP@yfa1\relax%
  394.        \advance\FP@xfb1000000000\relax%
  395.      \fi%
  396.      \advance\FP@xfa-\FP@yfa%
  397.      \ifnum\FP@xfa<0\relax%
  398.        \advance\FP@yib1\relax%
  399.        \advance\FP@xfa1000000000\relax%
  400.      \fi%
  401.      \advance\FP@xib-\FP@yib%
  402.      \ifnum\FP@xib<0\relax%
  403.        \advance\FP@yia1\relax%
  404.        \advance\FP@xib1000000000\relax%
  405.      \fi%
  406.      \advance\FP@xia-\FP@yia%
  407.      \ifnum\FP@xia<0\relax%
  408.        \FP@xs=-\FP@xs%
  409.        \ifnum\FP@xfb=0\relax\else%
  410.          \advance\FP@xfb-1000000000\relax\FP@xfb=-\FP@xfb%
  411.      \advance\FP@xfa1\relax%
  412.        \fi%
  413.        \ifnum\FP@xfa=0\relax\else%
  414.          \advance\FP@xfa-1000000000\relax\FP@xfa=-\FP@xfa%
  415.      \advance\FP@xib1\relax%
  416.        \fi%
  417.        \ifnum\FP@xib=0\relax\else%
  418.          \advance\FP@xib-1000000000\relax\FP@xib=-\FP@xib%
  419.      \advance\FP@xia1\relax%
  420.        \fi%
  421.        \relax\FP@xia=-\FP@xia%
  422.      \fi%
  423.      \FP@store\FP@tmp{x}%
  424.    \fi%
  425.    %
  426.    \global\let\FP@tmp\FP@tmp%
  427.    %
  428.    \FP@endmessage{}%
  429.   }%
  430.   \let#1\FP@tmp%
  431. }
  432.  
  433. %multiply two values
  434.  
  435. \def\FP@firstnine#1#2#3#4#5#6#7#8#9{%
  436.   \FP@res=#1#2#3#4#5#6#7#8#9\relax%
  437. }
  438. \def\FP@@ninesplit#1\relax#2\end#3{%
  439.   #1%
  440.   \edef#3{#2}%
  441. }
  442. \def\FP@ninesplit#1{%
  443.   \edef#1{\expandafter\FP@firstnine\FP@rd}%
  444.   \expandafter\FP@@ninesplit#1\end#1\relax%
  445. }
  446.  
  447. \def\FP@split#1#2#3#4{%
  448.   % #1 highest three digits
  449.   % #2 medium three digits
  450.   % #3 least three digits
  451.   % #4 counter
  452.   \FP@regc=#4%
  453.   \divide\FP@regc1000000\relax%
  454.   #1=\FP@regc%
  455.   \multiply\FP@regc-1000000\relax\advance\FP@regc#4%
  456.   #3=\FP@regc%
  457.   \divide\FP@regc1000\relax%
  458.   #2=\FP@regc%
  459.   \multiply\FP@regc-1000\relax\advance\FP@regc#3%
  460.   #3=\FP@regc%
  461. }
  462.  
  463. \def\FP@@mul#1#2#3{%
  464.   \FP@regc=\csname FP@x#1\endcsname%
  465.   \multiply\FP@regc\csname FP@y#2\endcsname%
  466.   \advance\FP@prod\FP@regc%
  467.   %
  468.   \ifx#3\relax%
  469.     \let\next=\relax% 
  470.   \else%
  471.     \let\next=\FP@@mul%
  472.   \fi%
  473.   \next#3%
  474. }
  475.  
  476. \def\FP@saveshift{%
  477.   % save rightmost three digits 
  478.   \FP@regc=\FP@prod%
  479.   \divide\FP@prod1000\relax%
  480.   \multiply\FP@prod1000\relax%
  481.   \advance\FP@regc-\FP@prod%
  482.   \advance\FP@regc1000\relax%
  483.   \edef\FP@rd{\expandafter\FP@ignorenext\the\FP@regc\FP@rd}%
  484.   %
  485.   \divide\FP@prod1000\relax%
  486. }
  487.  
  488. \def\FP@mul#1#2.#3.#4\relax#5.#6.#7\relax{%
  489.   % #1 macro, which gets the result
  490.   % #2 integer part of 1st value 
  491.   % #3 fractional part of 1st value
  492.   % #4 dummy to swallow everthing after the 2nd '.'
  493.   % #5 integer part of 2nd value 
  494.   % #6 fractional part of 2nd value
  495.   % #7 dummy to swallow everthing after the 2nd '.'
  496.   %
  497.   % split value in various parts
  498.   % x y = 123 456 789 123 456 789 . 123 456 789 123 456 789
  499.   % ->    xk  xl  xm  xn  xo  xp    xq  xr  xs  xt  xu  xv
  500.   % ->    yk  yl  ym  yn  yo  yp    yq  yr  ys  yt  yu  yv
  501.   % multiply these parts and save the result wrt the necessary shifts
  502.   %
  503.   {\FP@beginmessage{MUL}%
  504.    %
  505.    \FP@readvalue{x}{#2}{#3}%
  506.    \FP@readvalue{y}{#5}{#6}%
  507.    %
  508.    %sign
  509.    \multiply\FP@xs\FP@ys%
  510.    \FP@rs=\FP@xs%
  511.    %
  512.    % split parts
  513.    \FP@split\FP@xk\FP@xl\FP@xm\FP@xia \FP@split\FP@xn\FP@xo\FP@xp\FP@xib%
  514.    \FP@split\FP@xq\FP@xr\FP@xz\FP@xfa \FP@split\FP@xt\FP@xu\FP@xv\FP@xfb%
  515.    \FP@split\FP@yk\FP@yl\FP@ym\FP@yia \FP@split\FP@yn\FP@yo\FP@yp\FP@yib%
  516.    \FP@split\FP@yq\FP@yr\FP@yz\FP@yfa \FP@split\FP@yt\FP@yu\FP@yv\FP@yfb%
  517.    %
  518.    \FP@prod=0\relax%
  519.    \edef\FP@rd{}%
  520.    %
  521.    %compute result
  522.    \FP@@mul vv                         \relax\FP@saveshift%
  523.    \FP@@mul vu uv                    \relax\FP@saveshift%
  524.    \FP@@mul uu vt tv                     \relax\FP@saveshift%
  525.    \FP@@mul ut tu vz zv                 \relax\FP@saveshift%
  526.    \FP@@mul tt zu uz rv vr                \relax\FP@saveshift%
  527.    \FP@@mul zt tz ur ru vq qv                 \relax\FP@saveshift%
  528.    \FP@@mul zz rt tr uq qu vp pv              \relax\FP@saveshift%
  529.    \FP@@mul zr rz tq qt up pu vo ov             \relax\FP@saveshift%
  530.    \FP@@mul rr qz zq tp pt uo ou vn nv             \relax\FP@saveshift%
  531.    \FP@@mul rq qr zp pz to ot un nu vm mv       \relax\FP@saveshift%
  532.    \FP@@mul qq rp pr zo oz tn nt um mu vl lv    \relax\FP@saveshift%
  533.    \FP@@mul qp pq ro or zn nz tm mt ul lu kv vk \relax\FP@saveshift%
  534.    \FP@@mul pp oq qo rn nr zm mz tl lt ku uk    \relax\FP@saveshift%
  535.    \FP@@mul op po nq qn rm mr zl lz tk kt       \relax\FP@saveshift%
  536.    \FP@@mul oo pn np mq qm rl lr kz zk          \relax\FP@saveshift%
  537.    \FP@@mul no on mp pm lq ql kr rk             \relax\FP@saveshift%
  538.    \FP@@mul nn mo om pl lp qk kq             \relax\FP@saveshift%
  539.    \FP@@mul mn nm lo ok pk kp                 \relax\FP@saveshift%
  540.    \FP@@mul mm ln nl ko ok                 \relax\FP@saveshift%
  541.    \FP@@mul lm ml kn nk                    \relax\FP@saveshift%
  542.    \FP@@mul ll km mk                     \relax\FP@saveshift%
  543.    \FP@@mul kl lk                     \relax\FP@saveshift%
  544.    \FP@@mul kk                         \relax\FP@saveshift\FP@saveshift%
  545.    \FP@ninesplit\FP@rd%
  546.    \ifnum\FP@res=0\relax%
  547.      \FP@ninesplit\FP@rd%
  548.      \ifnum\FP@res=0\relax%
  549.        \FP@ninesplit\FP@rd\FP@ria=\FP@res%
  550.        \FP@ninesplit\FP@rd\FP@rib=\FP@res%
  551.        \FP@ninesplit\FP@rd\FP@rfa=\FP@res%
  552.        \FP@ninesplit\FP@rd\FP@rfb=\FP@res%
  553.        \FP@store\FP@tmp{r}%
  554.      \else%
  555.        \FP@errmessage{Overflow}%
  556.      \fi%
  557.    \else%
  558.      \FP@errmessage{Overflow}%
  559.    \fi%
  560.    %
  561.    \global\let\FP@tmp\FP@tmp%
  562.    %
  563.    \FP@endmessage{}%
  564.   }%
  565.   \let#1\FP@tmp%
  566. }
  567.  
  568. %divide one value by another one
  569.  
  570. \def\FP@divten#1{%
  571.   \expandafter\FP@regc\csname FP@#1ia\endcsname%
  572.   \expandafter\divide\csname FP@#1ia\endcsname10\relax%
  573.   \expandafter\FP@regb\csname FP@#1ia\endcsname%
  574.   \multiply\FP@regb10\relax%
  575.   \advance\FP@regc-\FP@regb%
  576.   \multiply\FP@regc100000000\relax%
  577.   %
  578.   \expandafter\FP@rega\csname FP@#1ib\endcsname%
  579.   \expandafter\divide\csname FP@#1ib\endcsname10\relax%
  580.   \expandafter\FP@regb\csname FP@#1ib\endcsname%
  581.   \multiply\FP@regb10\relax%
  582.   \advance\FP@rega-\FP@regb%
  583.   \multiply\FP@rega100000000\relax%
  584.   \expandafter\advance\csname FP@#1ib\endcsname\FP@regc%
  585.   %
  586.   \expandafter\FP@regc\csname FP@#1fa\endcsname%
  587.   \expandafter\divide\csname FP@#1fa\endcsname10\relax%
  588.   \expandafter\FP@regb\csname FP@#1fa\endcsname%
  589.   \multiply\FP@regb10\relax%
  590.   \advance\FP@regc-\FP@regb%
  591.   \multiply\FP@regc100000000\relax%
  592.   \expandafter\advance\csname FP@#1fa\endcsname\FP@rega%
  593.   %
  594.   \expandafter\divide\csname FP@#1fb\endcsname10\relax%
  595.   \expandafter\advance\csname FP@#1fb\endcsname\FP@regc%
  596. }
  597.  
  598. \def\FP@multen#1{%
  599.   \expandafter\multiply\csname FP@#1ia\endcsname10\relax%
  600.   \expandafter\ifnum\csname FP@#1ib\endcsname<100000000\relax%
  601.   \else%
  602.     \expandafter\FP@regc\csname FP@#1ib\endcsname%
  603.     \divide\FP@regc100000000%
  604.     \expandafter\advance\csname FP@#1ia\endcsname\FP@regc%
  605.     \multiply\FP@regc100000000%
  606.     \expandafter\advance\csname FP@#1ib\endcsname-\FP@regc%
  607.   \fi%
  608.   \expandafter\multiply\csname FP@#1ib\endcsname10\relax%
  609.   \expandafter\ifnum\csname FP@#1fa\endcsname<100000000\relax%
  610.   \else%
  611.     \expandafter\FP@regc\csname FP@#1fa\endcsname%
  612.     \divide\FP@regc100000000%
  613.     \expandafter\advance\csname FP@#1ib\endcsname\FP@regc%
  614.     \multiply\FP@regc100000000%
  615.     \expandafter\advance\csname FP@#1fa\endcsname-\FP@regc%
  616.   \fi%
  617.   \expandafter\multiply\csname FP@#1fa\endcsname10\relax%
  618.   \expandafter\ifnum\csname FP@#1fb\endcsname<100000000\relax%
  619.   \else%
  620.     \expandafter\FP@regc\csname FP@#1fb\endcsname%
  621.     \divide\FP@regc100000000%
  622.     \expandafter\advance\csname FP@#1fa\endcsname\FP@regc%
  623.     \multiply\FP@regc100000000%
  624.     \expandafter\advance\csname FP@#1fb\endcsname-\FP@regc%
  625.   \fi%
  626.   \expandafter\multiply\csname FP@#1fb\endcsname10\relax%
  627. }
  628.  
  629. \def\FP@counttimes{%
  630.   {\global\FP@times=0\relax%
  631.    \loop%
  632.      \ifnum%
  633.         \ifnum\FP@xia>\FP@yia1%
  634.     \else\ifnum\FP@xia<\FP@yia0%
  635.     \else%
  636.       \ifnum\FP@xib>\FP@yib1%
  637.       \else\ifnum\FP@xib<\FP@yib0%
  638.       \else%
  639.         \ifnum\FP@xfa>\FP@yfa1%
  640.         \else\ifnum\FP@xfa<\FP@yfa0%
  641.         \else%
  642.           \ifnum\FP@xfb>\FP@yfb1%
  643.           \else\ifnum\FP@xfb<\FP@yfb0%
  644.           \else%
  645.              1%
  646.           \fi\fi%
  647.         \fi\fi%
  648.       \fi\fi%
  649.     \fi\fi%
  650.     =1\relax%
  651.        \global\advance\FP@times1\relax%
  652.        \global\advance\FP@xfb-\FP@yfb%
  653.        \ifnum\FP@xfb<0\relax%
  654.          \global\advance\FP@xfb1000000000\relax%
  655.      \global\advance\FP@xfa-1\relax%
  656.        \fi%
  657.        \global\advance\FP@xfa-\FP@yfa%
  658.        \ifnum\FP@xfa<0\relax%
  659.          \global\advance\FP@xfa1000000000\relax%
  660.      \global\advance\FP@xib-1\relax%
  661.        \fi%
  662.        \global\advance\FP@xib-\FP@yib%
  663.        \ifnum\FP@xib<0\relax%
  664.          \global\advance\FP@xib1000000000\relax%
  665.      \global\advance\FP@xia-1\relax%
  666.        \fi%
  667.        \global\advance\FP@xia-\FP@yia%
  668.      \repeat%
  669.   }%
  670. }
  671.  
  672. \def\FP@div#1#2.#3.#4\relax#5.#6.#7\relax{%
  673.   % #1 macro, which gets the result
  674.   % #2 integer part of 1st value 
  675.   % #3 fractional part of 1st value
  676.   % #4 dummy to swallow everthing after the 2nd '.'
  677.   % #5 integer part of 2nd value 
  678.   % #6 fractional part of 2nd value
  679.   % #7 dummy to swallow everthing after the 2nd '.'
  680.   %
  681.   % algorithmic idea (for x>0, y>0)
  682.   %   - %determine \FP@shift  such that y*10^\FP@shift <100000000<=y*10^(\FP@shift+1)
  683.   %   - %determine \FP@shift' such that x*10^\FP@shift'<100000000<=x*10^(\FP@shift+1)
  684.   %   - x=x*\FP@shift'
  685.   %   - y=y*\FP@shift
  686.   %   - \FP@shift=\FP@shift-\FP@shift'
  687.   %   - res=0
  688.   %   - while y>0 %fixed-point representation!
  689.   %   -   \FP@times=0
  690.   %   -      while x>y
  691.   %   -     \FP@times=\FP@times+1
  692.   %   -     x=x-y
  693.   %   -   end
  694.   %   -   y=y/10
  695.   %   -   res=10*res+\FP@times/1000000000
  696.   %   - end
  697.   %   - %shift the result according to \FP@shift
  698.   %
  699.   {\FP@beginmessage{DIV}%
  700.    %
  701.    \FP@readvalue{x}{#2}{#3}%
  702.    \FP@readvalue{y}{#5}{#6}%
  703.    %
  704.    %sign
  705.    \multiply\FP@xs\FP@ys%
  706.    \FP@rs=\FP@xs%
  707.    %
  708.    %compute division
  709.    \ifFP@zero{y}%
  710.      \FP@errmessage{Division by zero}%
  711.    \else%
  712.      \ifFP@zero{x}\def\next##1{\edef\FP@tmp{0}}\else\def\next##1{##1}\fi%
  713.      \next%
  714.        {\FP@shift=0\relax%
  715.         \loop%
  716.           \ifnum\FP@yia<100000000\relax%
  717.          \FP@multen{y}%
  718.          \advance\FP@shift1\relax%
  719.        \repeat%
  720.         \loop%
  721.           \ifnum\FP@xia<100000000\relax%
  722.          \FP@multen{x}%
  723.          \advance\FP@shift-1\relax%
  724.       \repeat%
  725.         \FP@ria=0\FP@rib=0\FP@rfa=0\FP@rfb=0\relax%
  726.         \loop%
  727.           \ifFP@zero{y}\else%
  728.          \FP@counttimes%divides x by \FP@times*y
  729.          \FP@divten{y}%
  730.          \FP@multen{r}%
  731.          \advance\FP@rfb\FP@times%
  732.          \ifnum\FP@rfb<1000000000\relax\else%
  733.            \advance\FP@rfa1\advance\FP@rfb-1000000000\relax%
  734.            \ifnum\FP@rfa<1000000000\relax\else%
  735.              \advance\FP@rib1\advance\FP@rfa-1000000000\relax%
  736.          \ifnum\FP@rib<1000000000\relax\else%
  737.            \advance\FP@ria1\advance\FP@rib-1000000000\relax%
  738.          \fi%
  739.            \fi%
  740.          \fi%
  741.       \repeat%
  742.         \loop%
  743.           \ifnum\FP@shift>17%
  744.         \advance\FP@shift-1\relax%
  745.         \ifnum\FP@ria<100000000\else\FP@ria=-1\fi%
  746.         \ifnum\FP@ria<0\FP@ria=-1\fi%
  747.         \FP@multen{r}%
  748.       \repeat%
  749.         \ifnum\FP@ria<1000000000\else\FP@ria=-1\fi%
  750.         \loop%
  751.           \ifnum\FP@shift<17%
  752.         \advance\FP@shift1\relax%
  753.         \FP@divten{r}%
  754.       \repeat%
  755.         \ifnum\FP@ria<0\relax%
  756.           \FP@errmessage{Overflow}%
  757.         \else%
  758.           \FP@store\FP@tmp{r}%
  759.         \fi%
  760.        }%
  761.     \fi%
  762.    %
  763.    \global\let\FP@tmp=\FP@tmp%
  764.    %
  765.    \FP@endmessage{}%
  766.   }%
  767.   \let#1\FP@tmp%
  768. }
  769.  
  770. %absolute value
  771.  
  772. \def\FP@abs#1#2.#3.#4\relax{%
  773.   % #1 macro, which gets the result
  774.   % #2 integer part of value
  775.   % #3 fractional part of value
  776.   % #4 dummy to swallow everthing after the 2nd '.'
  777.   %
  778.   {\FP@beginmessage{ABS}%
  779.    %
  780.    \FP@readvalue{x}{#2}{#3}%
  781.    \FP@xs=1\relax%
  782.    \FP@store\FP@tmp{x}%
  783.    %
  784.    \global\let\FP@tmp\FP@tmp%
  785.    %
  786.    \FP@endmessage{}%
  787.   }%
  788.   \let#1\FP@tmp%
  789. }
  790.  
  791. %negate value
  792.  
  793. \def\FP@neg#1#2.#3.#4\relax{%
  794.   % #1 macro, which gets the result
  795.   % #2 integer part of value
  796.   % #3 fractional part of value
  797.   % #4 dummy to swallow everthing after the 2nd '.'
  798.   %
  799.   {\FP@beginmessage{NEG}%
  800.    %
  801.    \FP@readvalue{x}{#2}{#3}%
  802.    \multiply\FP@xs-1\relax%
  803.    \FP@store\FP@tmp{x}%
  804.    %
  805.    \global\let\FP@tmp\FP@tmp%
  806.    %
  807.    \FP@endmessage{}%
  808.   }%
  809.   \let#1\FP@tmp%
  810. }
  811.  
  812. %test if 1st value is less than 2nd value
  813.  
  814. \def\FP@iflt#1.#2.#3\relax#4.#5.#6\relax#7\relax{%
  815.   % #1 integer part of 1st value 
  816.   % #2 fractional part of 1st value
  817.   % #3 dummy to swallow everthing after the 2nd '.'
  818.   % #4 integer part of 2nd value 
  819.   % #5 fractional part of 2nd value
  820.   % #6 dummy to swallow everthing after the 2nd '.'
  821.   %
  822.   {\ifx#7+\relax%
  823.      \FP@beginmessage{LT?}%
  824.    \else%
  825.      \FP@beginmessage{GT?}%
  826.    \fi%
  827.    %
  828.    \FP@readvalue{x}{#1}{#2}%
  829.    \FP@readvalue{y}{#4}{#5}%
  830.    %
  831.    \ifnum\FP@xs<\FP@ys%
  832.      \FP@testtrue%
  833.    \else\ifnum\FP@xs>\FP@ys%
  834.      \FP@testfalse%
  835.    \else%
  836.      \ifnum\FP@xs>0\relax%
  837.         \ifnum\FP@xia<\FP@yia%
  838.           \FP@testtrue%
  839.         \else\ifnum\FP@xia>\FP@yia%
  840.           \FP@testfalse%
  841.         \else%
  842.           \ifnum\FP@xib<\FP@yib%
  843.         \FP@testtrue%
  844.       \else\ifnum\FP@xib>\FP@yib%
  845.         \FP@testfalse%
  846.       \else%
  847.         \ifnum\FP@xfa<\FP@yfa%
  848.           \FP@testtrue%
  849.         \else\ifnum\FP@xfa>\FP@yfa%
  850.           \FP@testfalse%
  851.         \else%
  852.           \ifnum\FP@xfb<\FP@yfb%
  853.             \FP@testtrue%
  854.           \else%
  855.             \FP@testfalse%
  856.           \fi%
  857.         \fi\fi%
  858.       \fi\fi%
  859.         \fi\fi%
  860.      \else%
  861.         \ifnum\FP@xia>\FP@yia%
  862.           \FP@testtrue%
  863.         \else\ifnum\FP@xia<\FP@yia%
  864.           \FP@testfalse%
  865.         \else%
  866.           \ifnum\FP@xib>\FP@yib%
  867.         \FP@testtrue%
  868.       \else\ifnum\FP@xib<\FP@yib%
  869.         \FP@testfalse%
  870.       \else%
  871.         \ifnum\FP@xfa>\FP@yfa%
  872.           \FP@testtrue%
  873.         \else\ifnum\FP@xfa<\FP@yfa%
  874.           \FP@testfalse%
  875.         \else%
  876.           \ifnum\FP@xfb>\FP@yfb%
  877.             \FP@testtrue%
  878.           \else%
  879.             \FP@testfalse%
  880.           \fi%
  881.         \fi\fi%
  882.       \fi\fi%
  883.         \fi\fi%
  884.      \fi%
  885.    \fi\fi%
  886.    %
  887.    \global\let\ifFP@test\ifFP@test%
  888.    %
  889.    \FP@endmessage{}%
  890.   }%
  891.   \let\ifFPtest\ifFP@test%
  892.   %
  893.   \ifFPtest%
  894. }
  895.  
  896. %test if two values are equal
  897.  
  898. \def\FP@ifeq#1.#2.#3\relax#4.#5.#6\relax{%
  899.   % #1 integer part of 1st value 
  900.   % #2 fractional part of 1st value
  901.   % #3 dummy to swallow everthing after the 2nd '.'
  902.   % #4 integer part of 2nd value 
  903.   % #5 fractional part of 2nd value
  904.   % #6 dummy to swallow everthing after the 2nd '.'
  905.   %
  906.   {\FP@beginmessage{EQ?}%
  907.    %
  908.    \FP@readvalue{x}{#1}{#2}%
  909.    \FP@readvalue{y}{#4}{#5}%
  910.    %
  911.    \ifnum\FP@xs=\FP@ys%
  912.      \ifnum\FP@xia=\FP@yia%
  913.        \ifnum\FP@xib=\FP@yib%
  914.          \ifnum\FP@xfa=\FP@yfa%
  915.        \ifnum\FP@xfb=\FP@yfb%
  916.          \FP@testtrue%
  917.         \else%
  918.          \FP@testfalse%
  919.        \fi%
  920.      \else%
  921.        \FP@testfalse%
  922.      \fi%
  923.        \else%
  924.          \FP@testfalse%
  925.        \fi%
  926.      \else%
  927.        \FP@testfalse%
  928.      \fi%
  929.    \else%
  930.      \FP@testfalse%
  931.    \fi%
  932.    %
  933.    \global\let\ifFP@test\ifFP@test%
  934.    %
  935.    \FP@endmessage{}%
  936.   }%
  937.   \let\ifFPtest\ifFP@test%
  938.   %
  939.   \ifFPtest%
  940. }
  941.  
  942. %test if value is negative
  943.  
  944. \def\FP@ifneg#1.#2.#3\relax{%
  945.   % #1 integer part of value
  946.   % #2 fractional part of value
  947.   % #3 dummy to swallow everthing after the 2nd '.'
  948.   %
  949.   {\FP@beginmessage{NEG?}%
  950.    %
  951.    \FP@readvalue{x}{#1}{#2}%
  952.    %
  953.    \ifnum\FP@xs<0\relax%
  954.      \FP@testtrue%
  955.    \else%
  956.      \FP@testfalse%
  957.    \fi%
  958.    %
  959.    \global\let\ifFP@test\ifFP@test%
  960.    %
  961.    \FP@endmessage{}%
  962.   }%
  963.   \let\ifFPtest\ifFP@test%
  964.   %
  965.   \ifFPtest%
  966. }
  967.  
  968. %test if value is positive
  969.  
  970. \def\FP@ifpos#1.#2.#3\relax{%
  971.   % #1 integer part of value
  972.   % #2 fractional part of value
  973.   % #3 dummy to swallow everthing after the 2nd '.'
  974.   %
  975.   {\FP@beginmessage{POS?}%
  976.    %
  977.    \FP@readvalue{x}{#1}{#2}%
  978.    %
  979.    \ifnum\FP@xs<0\relax%
  980.      \FP@testfalse%
  981.    \else%
  982.      \FP@testtrue%
  983.    \fi%
  984.    %
  985.    \global\let\ifFP@test\ifFP@test%
  986.    %
  987.    \FP@endmessage{}%
  988.   }%
  989.   \let\ifFPtest\ifFP@test%
  990.   %
  991.   \ifFPtest%
  992. }
  993.  
  994. %test if value is equal to zero
  995.  
  996. \def\FP@ifzero#1.#2.#3\relax{%
  997.   % #1 integer part of value
  998.   % #2 fractional part of value
  999.   % #3 dummy to swallow everthing after the 2nd '.'
  1000.   %
  1001.   {\FP@beginmessage{ZERO?}%
  1002.    %
  1003.    \FP@readvalue{x}{#1}{#2}%
  1004.    %
  1005.    \ifFP@zero{x}%
  1006.      \FP@testtrue%
  1007.    \else%
  1008.      \FP@testfalse%
  1009.    \fi%
  1010.    %
  1011.    \global\let\ifFP@test\ifFP@test%
  1012.    %
  1013.    \FP@endmessage{}%
  1014.   }%
  1015.   \let\ifFPtest\ifFP@test%
  1016.   %
  1017.   \ifFPtest%
  1018. }
  1019.  
  1020. %test if value is an integer
  1021.  
  1022. \def\FP@ifint#1.#2.#3\relax{%
  1023.   % #1 integer part of value
  1024.   % #2 fractional part of value
  1025.   % #3 dummy to swallow everthing after the 2nd '.'
  1026.   %
  1027.   {\FP@beginmessage{INT?}%
  1028.    %
  1029.    \FP@readvalue{x}{#1}{#2}%
  1030.    %
  1031.    \ifnum\FP@xfa=0\relax%
  1032.      \ifnum\FP@xfb=0\relax%
  1033.        \FP@testtrue%
  1034.      \else%
  1035.        \FP@testfalse%
  1036.      \fi%
  1037.    \else%
  1038.      \FP@testfalse%
  1039.    \fi%
  1040.    %
  1041.    \global\let\ifFP@test\ifFP@test%
  1042.    %
  1043.    \FP@endmessage{}%
  1044.   }%
  1045.   \let\ifFPtest\ifFP@test%
  1046.   %
  1047.   \ifFPtest%
  1048. }
  1049.